"""
认证和权限控制模块
"""
from fastapi import HTTPException, status, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from typing import Optional, List
from datetime import datetime, timedelta

from jose import JWTError, jwt
from core.config import settings
from core.database import get_db
from core.logging_config import get_logger
from core.exceptions import AuthenticationError, AuthorizationError
from models.user import User

# 安全认证
security = HTTPBearer()

# 日志记录器
logger = get_logger("petition_auth")


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
    """创建访问令牌"""
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=settings.access_token_expire_minutes)
    
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, settings.secret_key, algorithm=settings.algorithm)
    return encoded_jwt


def verify_token(token: str) -> dict:
    """验证令牌"""
    try:
        payload = jwt.decode(token, settings.secret_key, algorithms=[settings.algorithm])
        username: str = payload.get("sub")
        if username is None:
            raise AuthenticationError("无效的令牌")
        return payload
    except JWTError:
        raise AuthenticationError("令牌验证失败")


def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security),
    db: Session = Depends(get_db)
) -> User:
    """获取当前用户"""
    token = credentials.credentials
    payload = verify_token(token)
    username: str = payload.get("sub")
    
    user = db.query(User).filter(User.username == username, User.is_deleted == False).first()
    if user is None:
        raise AuthenticationError("用户不存在")
    
    if not user.is_active:
        raise AuthenticationError("用户已被禁用")
    
    return user


def get_current_user_from_token(token: str, db: Session) -> User:
    """从令牌获取当前用户"""
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )

    try:
        # 解码JWT令牌
        payload = jwt.decode(token, settings.secret_key, algorithms=[settings.algorithm])

        # 获取用户ID和用户名
        user_id = payload.get("user_id")
        username = payload.get("sub")

        user = None

        if user_id:
            # 优先通过用户ID查找
            try:
                user_id_int = int(user_id)
                user = db.query(User).filter(User.id == user_id_int).first()
            except (ValueError, TypeError):
                pass

        # 如果通过ID没找到，尝试通过用户名查找
        if user is None and username:
            user = db.query(User).filter(User.username == username).first()

        if user is None:
            raise credentials_exception

    except JWTError:
        raise credentials_exception

    if user is None:
        raise credentials_exception

    return user


def get_current_active_user(current_user: User = Depends(get_current_user)) -> User:
    """获取当前活跃用户"""
    if not current_user.is_active:
        raise HTTPException(status_code=400, detail="用户已被禁用")
    return current_user


def require_permissions(permission_codes: List[str]):
    """权限验证装饰器工厂 - 临时简化版本"""
    def check_permissions(current_user: User = Depends(get_current_user)):
        # 临时：只要用户登录就允许访问
        if current_user is None:
            raise AuthenticationError("用户未登录")

        # 记录权限检查日志
        logger.info(f"用户 {getattr(current_user, 'username', 'unknown')} 请求权限: {permission_codes}")

        # 临时：对所有已登录用户放行，用于调试权限问题
        return current_user

    return check_permissions


def require_role(role_names: List[str]):
    """角色验证装饰器工厂"""
    def check_roles(current_user: User = Depends(get_current_user)):
        # # 确保用户已登录
        # if current_user is None:
        #     raise AuthenticationError("用户未登录")
        
        # # 超级用户拥有所有角色权限
        # if hasattr(current_user, 'is_superuser') and callable(current_user.is_superuser):
        #     if current_user.is_superuser():
        #         return current_user
        # elif hasattr(current_user, 'is_superuser') and current_user.is_superuser:
        #     return current_user
        
        # # 检查用户是否拥有所需角色
        # if hasattr(current_user, 'get_role_names') and callable(current_user.get_role_names):
        #     user_role_names = current_user.get_role_names()
        # else:
        #     user_role_names = getattr(current_user, 'role_names', [])
        
        # for role_name in role_names:
        #     if role_name not in user_role_names:
        #         logger.warning(
        #             f"用户 {getattr(current_user, 'username', 'unknown')} 缺少角色: {role_name}",
        #             extra={
        #                 "user_id": getattr(current_user, 'id', None),
        #                 "required_roles": role_names,
        #                 "user_roles": user_role_names
        #             }
        #         )
        #         raise AuthorizationError(f"需要角色: {role_name}")
        
        return current_user
    
    return check_roles


def require_admin(permission_codes: List[str]):
    """管理员权限验证"""
    return require_permissions(permission_codes)


def require_permission(permission_code: str):
    """单个权限验证装饰器（便捷方法）"""
    return require_permissions([permission_code])


def require_superuser():
    """超级用户权限验证"""
    def check_superuser(current_user: User = Depends(get_current_user)):
        # # 确保用户已登录
        # if current_user is None:
        #     raise AuthenticationError("用户未登录")
        
        # if hasattr(current_user, 'is_superuser') and callable(current_user.is_superuser):
        #     if not current_user.is_superuser():
        #         raise AuthorizationError("需要超级用户权限")
        # elif hasattr(current_user, 'is_superuser') and not current_user.is_superuser:
        #     raise AuthorizationError("需要超级用户权限")
        # else:
        #     raise AuthorizationError("用户权限验证失败")
        
        return current_user
    
    return check_superuser


class PermissionChecker:
    """权限检查器类"""
    
    def __init__(self, db: Session):
        self.db = db
    
    def check_user_permission(self, user: User, permission_code: str) -> bool:
        """检查用户是否有指定权限"""
        if hasattr(user, 'is_superuser') and callable(user.is_superuser):
            if user.is_superuser():
                return True
        elif hasattr(user, 'is_superuser') and user.is_superuser:
            return True
        
        if hasattr(user, 'has_permission') and callable(user.has_permission):
            return user.has_permission(permission_code)
        else:
            return False
    
    def check_user_role(self, user: User, role_name: str) -> bool:
        """检查用户是否有指定角色"""
        if hasattr(user, 'is_superuser') and callable(user.is_superuser):
            if user.is_superuser():
                return True
        elif hasattr(user, 'is_superuser') and user.is_superuser:
            return True
        
        if hasattr(user, 'get_role_names') and callable(user.get_role_names):
            return role_name in user.get_role_names()
        else:
            return role_name in getattr(user, 'role_names', [])
    
    def get_user_permissions(self, user: User) -> List[str]:
        """获取用户权限列表"""
        if hasattr(user, 'is_superuser') and callable(user.is_superuser):
            if user.is_superuser():
                return ["*"]  # 超级用户拥有所有权限
        elif hasattr(user, 'is_superuser') and user.is_superuser:
            return ["*"]  # 超级用户拥有所有权限
        
        if hasattr(user, 'get_permission_codes') and callable(user.get_permission_codes):
            return user.get_permission_codes()
        else:
            return getattr(user, 'permission_codes', [])
    
    def get_user_roles(self, user: User) -> List[str]:
        """获取用户角色列表"""
        if hasattr(user, 'get_role_names') and callable(user.get_role_names):
            return user.get_role_names()
        else:
            return getattr(user, 'role_names', [])


def create_permission_dependency(permission_codes: List[str]):
    """创建权限依赖"""
    return Depends(require_permissions(permission_codes))


def create_role_dependency(role_names: List[str]):
    """创建角色依赖"""
    return Depends(require_role(role_names))


# 常用权限依赖
admin_dependency = create_permission_dependency(["admin_access"])
user_manage_dependency = create_permission_dependency(["user_manage"])
role_manage_dependency = create_permission_dependency(["role_manage"])
permission_manage_dependency = create_permission_dependency(["permission_manage"])
data_source_manage_dependency = create_permission_dependency(["data_source_manage"])
analysis_task_manage_dependency = create_permission_dependency(["analysis_task_manage"])
report_manage_dependency = create_permission_dependency(["report_manage"])
system_config_dependency = create_permission_dependency(["system_config"])

# 常用角色依赖
admin_role_dependency = create_role_dependency(["admin"])
manager_role_dependency = create_role_dependency(["manager"])
analyst_role_dependency = create_role_dependency(["analyst"])


class AuthMiddleware:
    """认证中间件"""
    
    def __init__(self, app):
        self.app = app
    
    async def __call__(self, scope, receive, send):
        # 这里可以添加全局认证逻辑
        return await self.app(scope, receive, send)


def init_default_permissions(db: Session):
    """初始化默认权限"""
    default_permissions = [
        # 管理员权限
        {"code": "admin_access", "name": "管理员访问", "description": "系统管理员访问权限"},
        {"code": "user_manage", "name": "用户管理", "description": "用户增删改查权限"},
        {"code": "role_manage", "name": "角色管理", "description": "角色增删改查权限"},
        {"code": "permission_manage", "name": "权限管理", "description": "权限增删改查权限"},
        
        # 数据源管理权限
        {"code": "data_source:create", "name": "创建数据源", "description": "创建新数据源权限"},
        {"code": "data_source:read", "name": "查看数据源", "description": "查看数据源信息权限"},
        {"code": "data_source:update", "name": "更新数据源", "description": "更新数据源配置权限"},
        {"code": "data_source:delete", "name": "删除数据源", "description": "删除数据源权限"},
        {"code": "data_source:test", "name": "测试数据源", "description": "测试数据源连接权限"},
        {"code": "data_source:query", "name": "查询数据源", "description": "查询数据源数据权限"},
        {"code": "data_source:admin", "name": "数据源管理", "description": "数据源管理权限"},
        
        # 分析任务权限
        {"code": "analysis_task_manage", "name": "分析任务管理", "description": "分析任务增删改查权限"},
        {"code": "analysis_task_execute", "name": "分析任务执行", "description": "分析任务执行权限"},
        {"code": "analysis_task_view", "name": "分析任务查看", "description": "分析任务查看权限"},
        
        # 分析结果权限
        {"code": "analysis_result_view", "name": "分析结果查看", "description": "分析结果查看权限"},
        {"code": "analysis_result_review", "name": "分析结果审核", "description": "分析结果审核权限"},
        
        # 统计分析权限
        {"code": "statistics_view", "name": "统计分析查看", "description": "统计分析查看权限"},
        {"code": "statistics_export", "name": "统计分析导出", "description": "统计分析导出权限"},
        
        # 报告管理权限
        {"code": "report_manage", "name": "报告管理", "description": "报告增删改查权限"},
        {"code": "report_generate", "name": "报告生成", "description": "报告生成权限"},
        {"code": "report_view", "name": "报告查看", "description": "报告查看权限"},
        
        # 系统配置权限
        {"code": "system_config", "name": "系统配置", "description": "系统配置权限"},
        {"code": "system_log", "name": "系统日志", "description": "系统日志查看权限"},
        {"code": "system_backup", "name": "系统备份", "description": "系统备份权限"},
    ]
    
    for perm_data in default_permissions:
        existing = db.query(Permission).filter(Permission.code == perm_data["code"]).first()
        if not existing:
            permission = Permission(**perm_data)
            db.add(permission)
    
    db.commit()


def init_default_roles(db: Session):
    """初始化默认角色"""
    # 获取所有权限
    permissions = db.query(Permission).filter(Permission.is_deleted == False).all()
    permission_map = {p.code: p for p in permissions}
    
    default_roles = [
        {
            "name": "admin",
            "description": "系统管理员",
            "permissions": list(permission_map.keys())  # 所有权限
        },
        {
            "name": "manager",
            "description": "数据管理专员",
            "permissions": [
                "data_source_manage", "data_source_view",
                "analysis_task_manage", "analysis_task_execute", "analysis_task_view",
                "analysis_result_view", "analysis_result_review",
                "statistics_view", "statistics_export"
            ]
        },
        {
            "name": "analyst",
            "description": "数据分析员",
            "permissions": [
                "data_source_view",
                "analysis_task_view",
                "analysis_result_view",
                "statistics_view",
                "report_view"
            ]
        },
        {
            "name": "viewer",
            "description": "查看者",
            "permissions": [
                "analysis_result_view",
                "statistics_view",
                "report_view"
            ]
        }
    ]
    
    for role_data in default_roles:
        existing = db.query(Role).filter(Role.name == role_data["name"]).first()
        if not existing:
            role = Role(
                name=role_data["name"],
                description=role_data["description"]
            )
            
            # 添加权限
            for perm_code in role_data["permissions"]:
                if perm_code in permission_map:
                    role.permissions.append(permission_map[perm_code])
            
            db.add(role)
    
    db.commit()


def create_default_admin_user(db: Session):
    """创建默认管理员用户"""
    admin_user = db.query(User).filter(User.username == "admin").first()
    if not admin_user:
        admin_user = User(
            username="admin",
            email="admin@example.com",
            password="admin",  # 在实际环境中应该使用强密码
            full_name="系统管理员",
            is_active=True
        )
        
        # 添加管理员角色
        admin_role = db.query(Role).filter(Role.name == "admin").first()
        if admin_role:
            admin_user.roles.append(admin_role)
        
        db.add(admin_user)
        db.commit()
        
        logger.info("默认管理员用户创建成功: admin/admin")
    
    return admin_user


def create_default_user(db: Session):
    """创建默认普通用户"""
    default_user = db.query(User).filter(User.username == "user").first()
    if not default_user:
        default_user = User(
            username="user",
            email="user@example.com",
            password="user",  # 在实际环境中应该使用强密码
            full_name="普通用户",
            role="user"
        )
        # 添加查看者角色
        db.add(default_user)
        db.commit()
        
        logger.info("默认普通用户创建成功: user/user")
    
    return default_user


def create_admin_user(db: Session):
    """创建默认普通用户"""
    admin_user = db.query(User).filter(User.username == "admin").first()
    if not admin_user:
        admin_user = User(
            username="admin",
            email="admin@example.com",
            password="admin",  # 在实际环境中应该使用强密码
            full_name="超级管理员",
            role="admin",
            is_active=True,
            is_superuser=True,
        )
        
        # 添加查看者角色
       
        db.add(admin_user)
        db.commit()
        
        logger.info("默认普通用户创建成功: user/user")
    
    return admin_user


def init_auth_data(db: Session):
    """初始化认证相关数据"""
    logger.info("开始初始化认证相关数据...")
    
    # # 初始化权限
    # init_default_permissions(db)
    
    # # 初始化角色
    # init_default_roles(db)
    
    # # 创建默认用户
    # create_default_admin_user(db)
    create_default_user(db)
    create_admin_user(db)

    
    logger.info("认证相关数据初始化完成")